﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TeaCompiler.CodeDom {

    /// <summary>
    /// 获取指定标识符信息。
    /// </summary>
    public static class TokenInfo {

        struct Token {

            public string Name;

            public byte Precedence;

        }

        readonly static Token[] _tokens = new Token[] {
            new Token(){Name = "<Illegal>", Precedence = 0},
            new Token(){Name = "<EOS>", Precedence = 0},
            new Token(){Name = "(", Precedence = 38},
            new Token(){Name = ")", Precedence = 0},
            new Token(){Name = "[", Precedence = 38},
            new Token(){Name = "]", Precedence = 0},
            new Token(){Name = "{", Precedence = 38},
            new Token(){Name = "}", Precedence = 0},
            new Token(){Name = ":", Precedence = 40},
            new Token(){Name = ";", Precedence = 100},
            new Token(){Name = "assert", Precedence = 4},
            new Token(){Name = "trace", Precedence = 4},
            new Token(){Name = "new", Precedence = 36},
            new Token(){Name = "typeof", Precedence = 36},
            new Token(){Name = "++", Precedence = 34},
            new Token(){Name = "--", Precedence = 34},
            new Token(){Name = "!", Precedence = 32},
            new Token(){Name = "~", Precedence = 32},
            new Token(){Name = "delete", Precedence = 32},
            new Token(){Name = "await", Precedence = 32},
            new Token(){Name = "+", Precedence = 28},
            new Token(){Name = "-", Precedence = 28},
            new Token(){Name = "&", Precedence = 20},
            new Token(){Name = "*", Precedence = 30},
            new Token(){Name = "..", Precedence = 4},
            new Token(){Name = "=>", Precedence = 36},
            new Token(){Name = ".", Precedence = 36},
            new Token(){Name = "->", Precedence = 36},
            new Token(){Name = "/", Precedence = 30},
            new Token(){Name = "%", Precedence = 30},
            new Token(){Name = "<<", Precedence = 26},
            new Token(){Name = ">>", Precedence = 26},
            new Token(){Name = "<", Precedence = 24},
            new Token(){Name = ">", Precedence = 24},
            new Token(){Name = "<=", Precedence = 24},
            new Token(){Name = ">=", Precedence = 24},
            new Token(){Name = "as", Precedence = 24},
            new Token(){Name = "is", Precedence = 24},
            new Token(){Name = "in", Precedence = 24},
            new Token(){Name = "to", Precedence = 24},
            new Token(){Name = "==", Precedence = 22},
            new Token(){Name = "!=", Precedence = 22},
            new Token(){Name = "^", Precedence = 18},
            new Token(){Name = "|", Precedence = 16},
            new Token(){Name = "&&", Precedence = 14},
            new Token(){Name = "||", Precedence = 12},
            new Token(){Name = "??", Precedence = 10},
            new Token(){Name = "or", Precedence = 10},
            new Token(){Name = "=", Precedence = 6},
            new Token(){Name = ":=", Precedence = 6},
            new Token(){Name = ":=:", Precedence = 6},
            new Token(){Name = "|=", Precedence = 6},
            new Token(){Name = "^=", Precedence = 6},
            new Token(){Name = "&=", Precedence = 6},
            new Token(){Name = "<<=", Precedence = 6},
            new Token(){Name = ">>=", Precedence = 6},
            new Token(){Name = "+=", Precedence = 6},
            new Token(){Name = "-=", Precedence = 6},
            new Token(){Name = "*=", Precedence = 6},
            new Token(){Name = "/=", Precedence = 6},
            new Token(){Name = "%=", Precedence = 6},
            new Token(){Name = "?", Precedence = 8},
            new Token(){Name = ",", Precedence = 2},
            new Token(){Name = "base", Precedence = 100},
            new Token(){Name = "break", Precedence = 100},
            new Token(){Name = "case", Precedence = 100},
            new Token(){Name = "catch", Precedence = 100},
            new Token(){Name = "const", Precedence = 100},
            new Token(){Name = "continue", Precedence = 100},
            new Token(){Name = "debugger", Precedence = 100},
            new Token(){Name = "default", Precedence = 100},
            new Token(){Name = "do", Precedence =100},
            new Token(){Name = "else", Precedence = 100},
            new Token(){Name = "finally", Precedence = 100},
            new Token(){Name = "for", Precedence = 100},
            new Token(){Name = "function", Precedence = 100},
            new Token(){Name = "goto", Precedence = 100},
            new Token(){Name = "if", Precedence =100},
            new Token(){Name = "import", Precedence = 100},
            new Token(){Name = "let", Precedence =100},
            new Token(){Name = "lock", Precedence = 100},
            new Token(){Name = "loop", Precedence = 100},
            new Token(){Name = "native", Precedence = 100},
            new Token(){Name = "once", Precedence = 100},
            new Token(){Name = "operator", Precedence = 100},
          //  new Token(){Name = "params", Precedence = 100},
            new Token(){Name = "ref", Precedence = 100},
            new Token(){Name = "return", Precedence = 100},
            new Token(){Name = "switch", Precedence = 100},
            new Token(){Name = "this", Precedence = 100},
            new Token(){Name = "throw", Precedence = 100},
            new Token(){Name = "try", Precedence = 100},
            new Token(){Name = "var", Precedence = 100},
            new Token(){Name = "while", Precedence = 100},
            new Token(){Name = "class", Precedence = 100},
            new Token(){Name = "struct", Precedence = 100},
            new Token(){Name = "enum", Precedence = 100},
            new Token(){Name = "interface", Precedence = 100},
            new Token(){Name = "extends", Precedence = 100},
            new Token(){Name = "event", Precedence = 100},
            new Token(){Name = "public", Precedence = 100},
            new Token(){Name = "internal", Precedence = 100},
            new Token(){Name = "protected", Precedence = 100},
            new Token(){Name = "private", Precedence = 100},
            new Token(){Name = "final", Precedence = 100},
            new Token(){Name = "static", Precedence = 100},
            new Token(){Name = "abstract", Precedence = 100},
            new Token(){Name = "virtual", Precedence = 100},
            new Token(){Name = "override", Precedence = 100},
            new Token(){Name = "volatile", Precedence = 100},
            new Token(){Name = "<Identifier>", Precedence = 101},
            new Token(){Name = "null", Precedence = 100},
            new Token(){Name = "true", Precedence = 100},
            new Token(){Name = "false", Precedence = 100},
            new Token(){Name = "<Int>", Precedence = 101},
            new Token(){Name = "<Hex>", Precedence = 101},
            new Token(){Name = "<Long>", Precedence = 101},
            new Token(){Name = "<UInt>", Precedence = 101},
            new Token(){Name = "<ULong>", Precedence = 101},
            new Token(){Name = "<Decimal>", Precedence = 101},
            new Token(){Name = "<Double>", Precedence = 101},
            new Token(){Name = "<Float>", Precedence = 101},
            new Token(){Name = "<String>", Precedence = 101},
            new Token(){Name = "<Char>", Precedence = 101},
            new Token(){Name = "<TemplateString>", Precedence = 101},
            new Token(){Name = "<TemplateChar>", Precedence = 101},
            new Token(){Name = "<Data>", Precedence = 101}
        };

        /// <summary>
        /// 获取标识符的优先级。
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static byte GetPrecedence(this TokenType type) {
            return _tokens[(int)type].Precedence;
        }

        /// <summary>
        /// 获取标识符的名字。
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static string GetName(this TokenType type) {
            return _tokens[(int)type].Name;
        }

        /// <summary>
        /// 获取标识符是否是唯一的字符串。
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static bool IsConst(this TokenType type) {
            return _tokens[(int)type].Precedence != 101;
        }

        public static bool IsPredefinedType(string typeName) {
            switch (typeName.Length) {
                case 3:
                    switch (typeName[0]) {
                        case 'i':
                            if (typeName[1] == 'n' && typeName[2] == 't') {
                                return true;
                            }
                            break;
                        case 'n':
                            if (typeName[1] == 'u' && typeName[2] == 'm') {
                                return true;
                            }
                            break;
                    }

                    break;
                case 4:
                    switch (typeName[3]) {
                        case 't':
                            if (typeName[0] == 'u' && typeName[1] == 'i' && typeName[2] == 'n') {
                                return true;
                            }
                            break;
                        case 'l':
                            if (typeName[0] == 'b' && typeName[1] == 'o' && typeName[2] == 'o') {
                                return true;
                            }
                            break;
                        case 'g':
                            if (typeName[0] == 'l' && typeName[1] == 'o' && typeName[2] == 'n') {
                                return true;
                            }
                            break;
                        case 'e':
                            if (typeName[0] == 'b' && typeName[1] == 'y' && typeName[2] == 't') {
                                return true;
                            }
                            break;
                        case 'r':
                            if (typeName[0] == 'c' && typeName[1] == 'h' && typeName[2] == 'a') {
                                return true;
                            }
                            break;
                    }
                    break;
                case 5:
                    switch (typeName[4]) {
                        case 't':
                            if (typeName[0] == 's' && typeName[1] == 'h' && typeName[2] == 'o' && typeName[3] == 'r') {
                                return true;
                            } else if (typeName[0] == 'f' && typeName[1] == 'l' && typeName[2] == 'o' && typeName[3] == 'a') {
                                return true;
                            } else if (typeName[0] == 's' && typeName[1] == 'b' && typeName[2] == 'y' && typeName[3] == 't') {
                                return true;
                            }
                            break;
                        case 'g':
                            if (typeName[0] == 'u' && typeName[1] == 'l' && typeName[2] == 'o' && typeName[3] == 'n') {
                                return true;
                            }
                            break;
                    }

                    break;
                case 6:
                    switch (typeName[0]) {
                        case 's':
                            if (typeName[1] == 't' && typeName[2] == 'r' && typeName[3] == 'i' && typeName[4] == 'n' && typeName[5] == 'g') {
                                return true;
                            }
                            break;
                        case 'd':
                            if (typeName[1] == 'o' && typeName[2] == 'u' && typeName[3] == 'b' && typeName[4] == 'l' && typeName[5] == 'e') {
                                return true;
                            }
                            break;
                        case 'u':
                            if (typeName[1] == 's' && typeName[2] == 'h' && typeName[3] == 'o' && typeName[4] == 'r' && typeName[5] == 't') {
                                return true;
                            }
                            break;
                    }

                    break;
                case 7:
                    switch (typeName[0]) {
                        case 'd':
                            if (typeName[1] == 'e' && typeName[2] == 'c' && typeName[3] == 'i' && typeName[4] == 'm' && typeName[5] == 'a' && typeName[6] == 'l') {
                                return true;
                            }
                            break;
                    }

                    break;


            }

            return false;
        }

    }
}
